//////////////////////////////////////////////////////////////////////////////////
//	 Copyright 2011 by Yosef Grabivker, ryuho@homenetworksoft.com
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//////////////////////////////////////////////////////////////////////////////////

#include <wx/wx.h>
#include <wx/sizer.h>
#include <wx/gbsizer.h>
#include <wx/combobox.h>

#include <ctype.h>
#include <algorithm>
#include <sstream>
#include "rcmdapp.h"
#include "mainwnd.h"
#include "adsltab.h"
#include "logicmanager.h"
#include "traficgraph.h"
#include "traficcolorselector.h"
#include "levelgraph.h"
#include "logicmanager.h"
#include "guicommon.h"
#include "linegraph.h"
#include "xmlguipanel.h"

using namespace std;

#define MAX_SNR					60

#define UPLOAD_SNR_NAME			wxT("Up. SNR")
#define DOWNLOAD_SNR_NAME		wxT("Dn. SNR")
#define UPLOAD_ATN_NAME			wxT("Up. Attn")
#define DOWNLOAD_ATN_NAME		wxT("Dn. Attn")

#define CRC_NAME				wxT("CRC")
#define LOS_NAME				wxT("LOS")
#define SEF_NAME				wxT("SEF")
#define INIT_NAME				wxT("Init")

#define D_CRC_NAME				wxT("Dn. CRC")
#define U_CRC_NAME				wxT("Up. CRC")
#define D_CRC_NAME				wxT("Dn. CRC")
#define U_FEC_NAME				wxT("Up. FEC")
#define D_FEC_NAME				wxT("Dn. FEC")
#define U_NCD_NAME				wxT("Up. NCD")
#define D_NCD_NAME				wxT("Dn. NCD")
#define U_LCD_NAME				wxT("Up. LCD")
#define D_OCD_NAME				wxT("Dn. OCD")
#define U_OCD_NAME				wxT("Up. OCD")
#define D_LCD_NAME				wxT("Dn. LCD")
#define U_HEC_NAME				wxT("Up. HEC")
#define D_HEC_NAME				wxT("Dn. HEC")

#define UCRC_ERR				wxT("Up. CRC/sec")
#define DCRC_ERR				wxT("Dn. CRC/sec")

#define MAX_RATE				wxT("Rate (Kbps)")


#define BITS_U_GRAPH			wxT("Up. Bits Per Tone")
#define BITS_D_GRAPH			wxT("Dn. Bits Per Tone")

#define SNR_TONE_GRAPH			wxT("SNR Per Tone")
#define SNR_TONE1_GRAPH			wxT("SNR1 Per Tone")
#define SNR_TONE2_GRAPH			wxT("SNR2 Per Tone")

typedef struct tagERROR
{
	size_t stLast;
	const char* szTag;
	wxString    strDesc;
}ERRATTR;

static ERRATTR errAttr[] =
{
	{ 0, ADSL_ESEC_ERR_ATTR, _("Err. Seconds")},
	{ 0, ADSL_CRC_ERR_ATTR, _("CRC")},
	{ 0, ADSL_LOS_ERR_ATTR, _("LOS")}, 
	{ 0, ADSL_SEF_ERR_ATTR, _("SELF")},
	{ 0, ADSL_INIT_ERR_ATTR, _("Init")}
};

static ERRATTR errAttrUp[]=
{
	{ 0, ADSL_U_SFE_ERR_ATTR, _("S.Frame Errs") },
	{ 0, ADSL_U_CRC_ERR_ATTR, _("CRC") },
	{ 0, ADSL_U_FEC_ERR_ATTR, _("FEC") },
	{ 0, ADSL_U_NCD_ERR_ATTR, _("NCD") },
	{ 0, ADSL_U_LCD_ERR_ATTR, _("LCD") },
	{ 0, ADSL_U_OCD_ERR_ATTR, _("OCD") },
	{ 0, ADSL_U_HEC_ERR_ATTR, _("HEC") }
};

static ERRATTR errAttrDn[]=
{
	{ 0, ADSL_D_SFE_ERR_ATTR, _("S.Frame Errs") },
	{ 0, ADSL_D_CRC_ERR_ATTR, _("CRC") },
	{ 0, ADSL_D_FEC_ERR_ATTR, _("FEC") },
	{ 0, ADSL_D_NCD_ERR_ATTR, _("NCD") },
	{ 0, ADSL_D_LCD_ERR_ATTR, _("LCD") },
	{ 0, ADSL_D_OCD_ERR_ATTR, _("OCD") },
	{ 0, ADSL_D_HEC_ERR_ATTR, _("HEC") }
};

enum cIDS
{
	ID_ANYLIZE=16100,
	ID_TIME_SELECTOR,
	ID_TIME_CRC_SELECTOR
};

BEGIN_EVENT_TABLE(CADSLTab, wxPanel)
	EVT_TEXT(ID_TIME_SELECTOR, 	CADSLTab::OnTimeRangeChanged)
	EVT_TEXT(ID_TIME_CRC_SELECTOR, 	CADSLTab::OnTimeCRCRangeChanged)
END_EVENT_TABLE()

#define GRAPH_W 120

CADSLTab::CADSLTab(class wxWindow* pParent):wxPanel(pParent), m_tInt(300)
{
	int nFlags=wxLEFT|wxRIGHT|wxDOWN|wxEXPAND|wxALIGN_CENTRE_VERTICAL;
	int nBorder=8;
	wxString label;

	wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
	wxBoxSizer* sizerGraph = new wxBoxSizer(wxVERTICAL);

	////////////////////////////////////////////////////////////////////
	label = _("Line Signal to Noise and Bits per tone capacity");
	wxStaticBoxSizer* pBoxCRC = new wxStaticBoxSizer( wxVERTICAL, this, label);
	m_pBitsPerTone = new CLineGraph(this);
	m_pBitsPerTone->SetMinSize(wxSize(100,GRAPH_W));
	pBoxCRC->Add( m_pBitsPerTone, 0, nFlags, nBorder );
	sizerGraph->Add( pBoxCRC, 0, nFlags, nBorder );

	{
		CLineGraph::GRAPHVISUAL visual;

		visual.cType= CLineGraph::cGraphTypeBar;
		visual.cPos = CLineGraph::cGraphLabelPositionLeft;
		visual.nPenWidth = 1;

		ZONERANGE zone;
		ZONELIST list;

		zone.color = wxColor(205,0,0);
		zone.nFrom = 0;
		zone.nTo   = 128;
		list.push_back(zone);

		visual.lstColors = list;

		m_pBitsPerTone->SetUpGraph(BITS_U_GRAPH, 16, visual);
	}

	{
		CLineGraph::GRAPHVISUAL visual;

		visual.cType= CLineGraph::cGraphTypeBar;
		visual.cPos = CLineGraph::cGraphLabelPositionLeft;
		visual.nPenWidth = 1;

		ZONERANGE zone;
		ZONELIST list;

		zone.color = wxColor(0,205,0);
		zone.nFrom = 128;
		zone.nTo   = 512;
		list.push_back(zone);

		visual.lstColors = list;

		m_pBitsPerTone->SetUpGraph(BITS_D_GRAPH, 16, visual);
	}

	{
		CLineGraph::GRAPHVISUAL visual;

		ZONERANGE zone;
		ZONELIST list;

		zone.color = wxColor(0,0,205);
		zone.nFrom = 0;
		zone.nTo   = 1024;
		list.push_back(zone);

		visual.cType= CLineGraph::cGraphTypeLine;
		visual.cPos = CLineGraph::cGraphLabelPositionRight;
		visual.lstColors = list;
		visual.nPenWidth = 2;

		m_pBitsPerTone->SetUpGraph(SNR_TONE_GRAPH, MAX_SNR, visual);
	}

	//////////////////////////////////////////////////////////////////////
	{
		wxBoxSizer* sizerSplitter = new wxBoxSizer(wxHORIZONTAL);

		int nsplFlags = wxGROW|wxALL;

		label = _("Signal to Noise Margins and Line Attenuation");
		{
			wxStaticBoxSizer* pBoxCRC = new wxStaticBoxSizer( wxVERTICAL, this, label );
			m_pLineSNR = new CLevelGraph(this, CLevelGraph::cNormalGraphMode, CLevelGraph::cGraphLabelBottom);
			m_pLineSNR->SetMinSize(wxSize(100,GRAPH_W));

			m_pLineSNR->SetColor(UPLOAD_SNR_NAME,	wxColor(0x50,0xB4,0x32) );
			m_pLineSNR->SetColor(DOWNLOAD_SNR_NAME, wxColor(0x00,0x00,0xCD) );
			m_pLineSNR->SetColor(UPLOAD_ATN_NAME,	wxColor(0xED,0x56,0x1B) );
			m_pLineSNR->SetColor(DOWNLOAD_ATN_NAME, wxColor(0x05,0x8D,0xC7) );

			pBoxCRC->Add( m_pLineSNR, 0, nsplFlags, 0 );
			sizerSplitter->Add( pBoxCRC, 1, nsplFlags, 5 );
		}

		label = _("Errors per second");
		{
			wxStaticBoxSizer* pBoxCRC = new wxStaticBoxSizer( wxVERTICAL, this, label);
			m_pErrorGraph = new CLevelGraph(this, CLevelGraph::cGrowBarGraphMode, CLevelGraph::cGraphLabelBottom);
			m_pErrorGraph->SetMinSize(wxSize(100,GRAPH_W));
			m_pErrorGraph->SetMesureName(_("errs"));
			pBoxCRC->Add( m_pErrorGraph, 0, nsplFlags, 0 );
			sizerSplitter->Add( pBoxCRC, 1, nsplFlags, 5 );

			m_pErrorGraph->SetColor(LOS_NAME, wxColor(0x33,0x66,0xCC));
			m_pErrorGraph->SetColor(SEF_NAME, wxColor(0xCC,0x33,0x00));
			m_pErrorGraph->SetColor(INIT_NAME, wxColor(0x00,0x33,0x00));

			m_pErrorGraph->SetColor(CRC_NAME,wxColor(0x99,0x00,0x00));
			m_pErrorGraph->SetColor(D_CRC_NAME,wxColor(0x99,0x00,0x00));
			m_pErrorGraph->SetColor(U_CRC_NAME,wxColor(0xFF,0x00,0x00));

			m_pErrorGraph->SetColor(D_FEC_NAME,wxColor(0x00,0x66,0x66));
			m_pErrorGraph->SetColor(U_FEC_NAME,wxColor(0x00,0x99,0x99));

			m_pErrorGraph->SetColor(D_NCD_NAME,wxColor(0x00,0x00,0x66));
			m_pErrorGraph->SetColor(U_NCD_NAME,wxColor(0x33,0x33,0xFF));

			m_pErrorGraph->SetColor(D_LCD_NAME,wxColor(0x66,0x00,0x66));
			m_pErrorGraph->SetColor(U_LCD_NAME,wxColor(0xCC,0x00,0xCC));

			m_pErrorGraph->SetColor(D_OCD_NAME,wxColor(0x00,0xcd,0xcd));
			m_pErrorGraph->SetColor(U_OCD_NAME,wxColor(0xCC,0xff,0xff));

			m_pErrorGraph->SetColor(D_HEC_NAME,wxColor(0x66,0x33,0x00));
			m_pErrorGraph->SetColor(U_HEC_NAME,wxColor(0xCC,0x99,0x00));
		}
		sizerGraph->Add(sizerSplitter, 1, wxGROW);
	}
	//////////////////////////////////////////////////////////////////////

	sizer->Add(sizerGraph, 0, wxALL|wxEXPAND, 5);
	
	///////////////////////////////////////
	m_pAnylizeWindow = new wxHtmlWindow(this,ID_ANYLIZE, wxDefaultPosition, wxSize(100,100), wxHW_SCROLLBAR_AUTO );
	sizer->Add(m_pAnylizeWindow, 1, wxALL|wxEXPAND);

	m_pAdvanced = new CXMLGUIPanel(this, this);
	sizer->Add(m_pAdvanced, 0, wxALL|wxEXPAND);
	
	SetSizer(sizer);

	ShowAnalyze();
	ShowAdvanced(false);

	sizer->FitInside(this);

	SetTimeInterval(m_tInt);

	//m_strXML = "<doc/>";
	//ProcessResponse();
}

void CADSLTab::SetTimeInterval(size_t tInt)
{
	m_tInt = tInt;

	m_pErrorGraph->SetTimePeriod(tInt);
	m_pLineSNR->SetTimePeriod(tInt);
}


CADSLTab::~CADSLTab()
{
}

void CADSLTab::OnTimeRangeChanged(wxCommandEvent& ev)
{
	wxComboBox* pComboBox = (wxComboBox* )ev.GetEventObject();

	int nSel = pComboBox->GetCurrentSelection();

	if ( wxNOT_FOUND!=nSel )
	{
		void* p = pComboBox->GetClientData(nSel);
		int	timeRange = (int)p;
	}
}

void CADSLTab::OnTimeCRCRangeChanged(wxCommandEvent& ev)
{
	wxComboBox* pComboBox = (wxComboBox* )ev.GetEventObject();

	int nSel = pComboBox->GetCurrentSelection();

	if ( wxNOT_FOUND!=nSel )
	{
		void* p = pComboBox->GetClientData(nSel);
		int	timeRange = (int)p;

		//m_pLineErr->SetTimePeriod(timeRange);
	}
}


//IGUIBind
void CADSLTab::OnResponse(const COMMANDRESPONSE& resp)
{
	try
	{
		if ( cCmdGetModemStats == resp.code )
		{
			m_data = resp.strData;
			m_strXML = resp.strXML;

			std::string strCaps = wxGetApp().GetMainWnd()->GetLogic().GetModemCaps(); 
			m_pAdvanced->SetCapsXML(strCaps);
	
			ProcessResponse();
			ShowAnalyze();
			
			m_pAdvanced->SetStatXML(m_strXML);
		}
	}
	catch (...)
	{
	}
}

bool CADSLTab::IsADSLBuiltIN()
{
	return !m_strXML.empty();
}

bool CADSLTab::IsADSLineConnected()
{
	bool bRes(false);

	CMarkupSTL	doc;
	
	if ( doc.SetDoc( m_strXML.c_str() ) )
	{
		if ( doc.FindChildElem(ADSL_STAT_TAG) )
		{
			if ( doc.GetChildAttrib(ADSL_ISUP_ATTR)=="true" )
			{
				bRes = true;
			}
		}
	}

	return bRes;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//IGUISupport
wxString CADSLTab::Save()
{
	wxString str;

	str = wxString::FromAscii(m_data.c_str());
	

	return str;
}

bool CADSLTab::CanShowAdvanced()
{
	return false==wxGetApp().GetMainWnd()->GetLogic().GetModemCaps().empty();
}

bool CADSLTab::IsAdvancedShown()
{
	return GetSizer()->IsShown(m_pAdvanced);
}

void CADSLTab::ShowAdvanced(bool bShow/*=true*/)
{
	if ( bShow )
	{
		std::string strCaps = wxGetApp().GetMainWnd()->GetLogic().GetModemCaps(); 
		m_pAdvanced->ShowAdvanced(bShow, strCaps);

		//wxRect rc = m_pAnylizeWindow->GetRect();
		//rc.height=100;
		//m_pAnylizeWindow->SetSize(rc, wxSIZE_AUTO_WIDTH);

		GetSizer()->Show(m_pAdvanced, true);
	}
	else
	{
		GetSizer()->Show(m_pAdvanced, false);
	}

	//GetSizer()->FitInside(this);
	GetSizer()->Layout();

	//GetSizer()->CalcMin();
	//GetSizer()->RecalcSizes();
	//GetSizer()->FitInside(this);
}

void CADSLTab::ProcessResponse()
{
	CMarkupSTL	doc;

	if ( doc.SetDoc( m_strXML.c_str() ) )
	{
		doc.FindChildElem(ADSL_STAT_TAG);

		long lVal;
		time_t tNow = time(NULL);

		//Graph
		lVal = atol ( doc.GetChildAttrib(ADSL_D_ATTN_ATTR).c_str());
		m_pLineSNR->SetData(DOWNLOAD_ATN_NAME,lVal, tNow);
		lVal = atol ( doc.GetChildAttrib(ADSL_U_ATTN_ATTR).c_str());
		m_pLineSNR->SetData(UPLOAD_ATN_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_U_SNR_ATTR).c_str());
		m_pLineSNR->SetData(UPLOAD_SNR_NAME,lVal, tNow);
		lVal = atol ( doc.GetChildAttrib(ADSL_D_SNR_ATTR).c_str());
		m_pLineSNR->SetData(DOWNLOAD_SNR_NAME,lVal, tNow);


		//////////////////////////////////////////////////////////
		lVal = atol ( doc.GetChildAttrib(ADSL_CRC_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(CRC_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_LOS_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(LOS_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_SEF_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(SEF_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_INIT_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(INIT_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_D_CRC_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(D_CRC_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_U_CRC_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(U_CRC_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_D_FEC_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(D_FEC_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_U_FEC_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(U_FEC_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_D_NCD_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(D_NCD_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_U_NCD_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(U_NCD_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_D_LCD_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(D_LCD_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_U_LCD_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(U_LCD_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_D_OCD_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(D_OCD_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_U_OCD_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(U_OCD_NAME,lVal, tNow);


		lVal = atol ( doc.GetChildAttrib(ADSL_D_HEC_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(D_HEC_NAME,lVal, tNow);

		lVal = atol ( doc.GetChildAttrib(ADSL_U_HEC_ERR_ATTR).c_str());
		m_pErrorGraph->SetDataEx(U_HEC_NAME,lVal, tNow);

		if ( IsADSLineConnected() )
		{
			if ( doc.FindChildElem(ADSL_BITS_U_TAG) )
			{
				doc.IntoElem();

				LINEVALS vl;

				for(size_t i=0;i<512;i++)
					vl.push_back( 0 );

				try
				{
					while ( doc.FindChildElem() )
					{
						long lIDX = atol( doc.GetChildAttrib(ADSL_TONE_ID_ATTR).c_str() );

						if ( lIDX<vl.size() )
						{
							long lVal = atol( doc.GetChildAttrib(ADSL_TONE_VAL_ATTR).c_str() );
							vl[lIDX] = lVal;
						}
					}
				}catch(...)
				{
				}

				m_pBitsPerTone->SetData(BITS_U_GRAPH, vl);

				doc.OutOfElem();
			}

			if ( doc.FindChildElem(ADSL_BITS_D_TAG) )
			{
				doc.IntoElem();

				LINEVALS vl;

				for(size_t i=0;i<512;i++)
					vl.push_back( 0 );

				try
				{
					while ( doc.FindChildElem() )
					{
						long lIDX = atol( doc.GetChildAttrib(ADSL_TONE_ID_ATTR).c_str() );

						if ( lIDX<vl.size() )
						{
							long lVal = atol( doc.GetChildAttrib(ADSL_TONE_VAL_ATTR).c_str() );
							vl[lIDX] = lVal;
						}
					}
				}catch(...)
				{
				}

				m_pBitsPerTone->SetData(BITS_D_GRAPH, vl);

				doc.OutOfElem();
			}

			if ( doc.FindChildElem(ADSL_SNR1_BIT_TAG) )
			{
				doc.IntoElem();

				LINEVALS vl;

				while ( doc.FindChildElem() )
				{
					long lVal = atol( doc.GetChildAttrib(ADSL_TONE_VAL_ATTR).c_str() );
					vl.push_back( lVal );
				}

				m_pBitsPerTone->SetData(SNR_TONE_GRAPH, vl);

				doc.OutOfElem();
			}

			/*
			if ( doc.FindChildElem(ADSL_SNR2_BIT_TAG) )
			{
				doc.IntoElem();

				LINEVALS vl;

				while ( doc.FindChildElem() )
				{
					long lVal = atol( doc.GetChildAttrib(ADSL_TONE_VAL_ATTR).c_str() );
					vl.push_back( lVal );
				}

				m_pBitsPerTone->SetData(SNR_TONE1_GRAPH, vl);

				doc.OutOfElem();
			}

			if ( doc.FindChildElem(ADSL_SNR3_BIT_TAG) )
			{
				doc.IntoElem();

				LINEVALS vl;

				while ( doc.FindChildElem() )
				{
					long lVal = atol( doc.GetChildAttrib(ADSL_TONE_VAL_ATTR).c_str() );
					vl.push_back( lVal );
				}

				m_pBitsPerTone->SetData(SNR_TONE2_GRAPH, vl);

				doc.OutOfElem();
			}*/
		}
		else
		{
			Reset();
		}
	}
}

void CADSLTab::Reset()
{
	m_pBitsPerTone->Reset();
	m_pLineSNR->Reset();
	m_pErrorGraph->Reset();

	ShowAnalyze();
}

wxString LineAttention(unsigned int nVal, bool& bLog)
{
	wxString str;

	bLog = false;

	if (!nVal)
	{
		return _("Bad. Will experience connectivity issues");
	}

	if (nVal<=20)
	{
		str = _("Outstanding");
	}
	else
	if (nVal<=30)
	{
		str = _("Excellent");
	}
	else
	if (nVal<=40)
	{
		str = _("Very good");
	}
	else
	if (nVal<=50)
	{
		str = _("Good");
	}
	else
	if (nVal<=60)
	{
		str = _("Poor. May experience connectivity issues");
		bLog = true;
	}
	else
	{
		str = _("Bad. Will experience connectivity issues");
		bLog = true;
	}

	return str;
}

wxString LineMargin(unsigned int nVal, bool& bLog)
{
	wxString str;

	bLog = false;

	if (nVal<6)
	{
		bLog = true;
		str = _("Bad. Will experience no synch or intermittent synch problems");
	}
	else
	if (nVal<=10)
	{
		str = _("Fair");
	}
	else
	if (nVal<=20)
	{
		str = _("Good");
	}
	else
	if (nVal<=28)
	{
		str = _("Excellent");
	}
	else
	{
		str = _("Outstanding");
	}

	return str;
}

wxString NoStatus(unsigned int nVal, bool& bLog)
{
	bLog = false;

	return wxT("-");
}


void CADSLTab::ShowAnalyze()
{
	int nCount(0);

	if ( m_pAnylizeWindow )
	{
		wxString strTemplate(wxT("<html><body>%s</body></html>"));
		wxString str;

		str+=wxT("<center><font size='4'>");

		if ( IsADSLBuiltIN() )
		{
			if ( IsADSLineConnected() )
			{
				str+=wxT("<b>");
				str+=_("ADSL line statistics");
				str+=wxT("</b>");
			}
			else
			{
				str+=wxT("<b>");
				str+=_("ADSL line disconnected");				
				str+=wxT("</b>");
			}
		}
		else
		{
			str+=wxT("<b>");
			str+=_("ADSL line statistics not available");
			str+=wxT("</b>");
		}

		str+=wxT("</font></center>");

		str+=wxT("<font size='2' face='Verdana'>");

		if ( IsADSLBuiltIN() )
		{
			bool bProblemFound(false);

			str+=wxT("<table border='0' style='border-collapse: collapse' cellspacing='0' cellpadding='1' width='100%'>");
			str+=wxT("<tr bgcolor='#84CAF9'>");
			str+=wxT("<th align='left'><b>");
			str+=_("Parameter");
			str+=wxT("</b></th>");
			str+=wxT("<th align='left'><b>");
			str+=_("Value");
			str+=wxT("</b></th>");
			str+=wxT("<th align='left'><b>");
			str+=_("Quality");
			str+=wxT("</b></th>");
			str+=wxT("</tr>");

			CMarkupSTL	doc;

			if ( doc.SetDoc( m_strXML.c_str() ) )
			{
				if ( doc.FindChildElem(ADSL_STAT_TAG) )
				{
					str+=AddTableLineTxt(doc, ADSL_LINE_STATUS_ATTR,_("Status"), wxT("%d"), NoStatus, nCount);

					str+=AddTableLineTxt(doc, ADSL_MODE_ATTR,_("Mode"), wxT("%3.d"), NoStatus, nCount);
					str+=AddTableLineTxt(doc, ADSL_CHANEL_ATTR,_("Type"), wxT("%3.d"), NoStatus, nCount);
					str+=AddTableLineTxt(doc, ADSL_TRELLIS_ATTR,_("Trellis"), wxT("%3.d"), NoStatus, nCount);
					str+=AddTableLineTxt(doc, ADSL_LINK_POWER_STATE_ATTR,_("Link Power State"), wxT("%3.d"), NoStatus, nCount);
					str+=AddTableLine(doc, ADSL_DISC_COUNT_ATTR,_("Disconnect count"), wxT("%d"), NoStatus, nCount);

					str+=AddTableLine(doc, ADSL_D_ATTN_ATTR,_("Downstream Line Attenuation"), wxT("%3.d db"), LineAttention, nCount);
					str+=AddTableLine(doc, ADSL_U_ATTN_ATTR,_("Upstream Line Attenuation"), wxT("%3.d db"), LineAttention, nCount);

					str+=AddTableLine(doc, ADSL_D_SNR_ATTR,_("Downstream SNR Margin"), wxT("%3.d db"), LineMargin, nCount);
					str+=AddTableLine(doc, ADSL_U_SNR_ATTR,_("Upstream SNR Margin"), wxT("%3.d db"), LineMargin, nCount);

					str+=AddTableLine(doc, ADSL_D_PWR_ATTR,_("Downstream Output Power"), wxT("%3.d dBm"), NoStatus, nCount);
					str+=AddTableLine(doc, ADSL_U_PWR_ATTR,_("Upstream Output Power"), wxT("%3.d dBm"), NoStatus, nCount);

					str+=AddTableLine(doc, ADSL_D_CONRATE_ATTR,_("Download Connection Rate"), wxT("%3.d kbs"), NoStatus, nCount);
					str+=AddTableLine(doc, ADSL_U_CONRATE_ATTR,_("Upload Connection Rate"), wxT("%3.d kbs"), NoStatus, nCount);

					str+=AddTableLine(doc, ADSL_D_MAXRATE_ATTR,_("Download Attainable Rate"), wxT("%3.d kbs"), NoStatus, nCount);
					str+=AddTableLine(doc, ADSL_U_MAXRATE_ATTR,_("Upload Attainable Rate"), wxT("%3.d kbs"), NoStatus, nCount);
				}
			
				str+=wxT("</table>");

				//Errors
				str+=wxT("<table border='0' style='border-collapse: collapse' cellspacing='0' cellpadding='1' width='100%'>");
				str+=wxT("<tr bgcolor='#84CAF9'>");
				str+=wxT("<th colspan=20 align='left'><b>");
				str+=_("Errors");
				str+=wxT("</b></th>");
				str+=wxT("</tr>");
				str+=wxT("</table>");

				bool bOk(false);
				int lVal;

				for(size_t i=0;i<sizeof(errAttr)/sizeof(errAttr[0]);i++ )
				{
					lVal = atol ( doc.GetChildAttrib(errAttr[i].szTag).c_str());
					if ( lVal )
					{
						if ( lVal<errAttr[i].stLast) errAttr[i].stLast=0;

						if (!bOk)
						{
							bOk = true;
							str+=wxT("<table border='0' style='border-collapse: collapse' cellspacing='0' cellpadding='1' width='100%'>");
						}
						str+=wxT("<tr>");
						str+=wxT("<td>");
						str+=errAttr[i].strDesc;
						str+=wxT(": ");
						str+=wxString::Format(wxT("<font color='red'>%d (+%d)</font></td>"), lVal, errAttr[i].stLast?lVal-errAttr[i].stLast:0 ); errAttr[i].stLast = lVal;
					}
				}

				if ( bOk )
				{
					bOk = false;
					str+=wxT("</table>");
				}

				for(size_t i=0;i<sizeof(errAttrUp)/sizeof(errAttrUp[0]);i++ )
				{
					lVal = atol ( doc.GetChildAttrib(errAttrUp[i].szTag).c_str());
					if ( lVal )
					{
						if ( lVal<errAttrUp[i].stLast) errAttrUp[i].stLast=0;

						if (!bOk)
						{
							bOk = true;
							str+=wxT("<table border='0' style='border-collapse: collapse' cellspacing='0' cellpadding='1' width='100%'>");
							str+=wxT("<tr bgcolor='#84CAF9'>");
							str+=wxT("<th colspan=20 align='left'><b>");
							str+=_("Upstream Errors");
							str+=wxT("</b></th>");
							str+=wxT("</tr>");
							str+=wxT("<tr>");
						}
						str+=wxT("<td>");
						str+=errAttrUp[i].strDesc;
						str+=wxT(": ");
						str+=wxString::Format(wxT("<font color='red'>%d (+%d)</font></td>"), lVal, errAttrUp[i].stLast?lVal-errAttrUp[i].stLast:0 ); errAttrUp[i].stLast = lVal;
					}
				}

				if ( bOk )
				{
					bOk = false;
					str+=wxT("</tr></table>");
				}

				for(size_t i=0;i<sizeof(errAttrDn)/sizeof(errAttrDn[0]);i++ )
				{
					lVal = atol ( doc.GetChildAttrib(errAttrDn[i].szTag).c_str());
					if ( lVal )
					{
						if ( lVal<errAttrDn[i].stLast) errAttrDn[i].stLast=0;

						if (!bOk)
						{
							bOk = true;
							str+=wxT("<table border='0' style='border-collapse: collapse' cellspacing='0' cellpadding='1' width='100%'>");
							str+=wxT("<tr bgcolor='#84CAF9'>");
							str+=wxT("<th colspan=20 align='left'><b>");
							str+=_("Downstream Errors");
							str+=wxT("</b></th>");
							str+=wxT("</tr>");
							str+=wxT("<tr>");
						}
						str+=wxT("<td>");
						str+=errAttrDn[i].strDesc;
						str+=wxT(": ");
						str+=wxString::Format(wxT("<font color='red'>%d (+%d)</font></td>"), lVal, errAttrDn[i].stLast?lVal-errAttrDn[i].stLast:0 ); errAttrDn[i].stLast = lVal;
					}
				}

				if ( bOk )
				{
					bOk = false;
					str+=wxT("</tr></table>");
				}
			}
		}

		str+=wxT("</font>");

		m_pAnylizeWindow->SetPage( wxString::Format(strTemplate,str.c_str()) );

		GetSizer()->FitInside(this);
		GetSizer()->Layout();
	}
}



wxString CADSLTab::AddTableLine(class CMarkupSTL&	doc, const char* szAttrib,
								const wxString& strParamName,const wxString& strParamMis,
								OnStatus st,int& nOrder)
{
	unsigned int nVal(0);

	std::string strVal = doc.GetChildAttrib( szAttrib );

	if ( strVal.empty() )
		return wxT("");

	nVal = atol( strVal.c_str() );

	return AddTableLine(nVal, strParamName,  strParamMis, st, nOrder);
}

wxString CADSLTab::AddTableLineTxt(class CMarkupSTL&	doc, const char* szAttrib,
								const wxString& strParamName,const wxString& strParamMis,
								OnStatus st,int& nOrder)
{
	unsigned int nVal(0);

	std::string strVal = doc.GetChildAttrib( szAttrib );

	if ( strVal.empty() )
		return wxT("");

	return AddTableLine( wxString::FromAscii( strVal.c_str() ), strParamName,  strParamMis, st, nOrder);
}

wxString CADSLTab::AddTableLine(unsigned long nVal, const wxString& strParamName,
								const wxString& strParamMis, OnStatus st, int& nOrder)
{
	wxString str, strStatus;

	bool bLog(false);

	if ( (nOrder%2)!=0)
	{
		str+=wxT("<tr bgcolor='#CCCCCC'>");
	}
	else
	{
		str+=wxT("<tr>");
	}

	str+=wxT("<td><b>");
	str+=strParamName;
	str+=wxT("</b></td>");

	str+=wxT("<td><b>");
	str+=wxString::Format(strParamMis, nVal);
	str+=wxT("</b></td>");

	str+=wxT("<td><b>");
	strStatus = st(nVal, bLog);
	str+=strStatus;
	str+=wxT("</b></td>");

	str+=wxT("</tr>");

	++nOrder;

	if ( bLog )
	{
		LOGENTRY entry;
		entry.strCustomEvent = _("ADSL line problem detected");
		entry.strCustomEvent+=wxT(": ");
		entry.strCustomEvent+= strParamName;
		entry.strCustomEvent+=wxT(" ");
		entry.strCustomEvent+=strStatus;

		wxGetApp().GetMainWnd()->GetLogic().AddToLog(entry, 3600);
	}

	return str;
}

wxString CADSLTab::AddTableLine(const wxString& strTxt, const wxString& strParamName,
								const wxString& strParamMis, OnStatus st, int& nOrder)
{
	wxString str, strStatus;

	bool bLog(false);

	if ( (nOrder%2)!=0)
	{
		str+=wxT("<tr bgcolor='#CCCCCC'>");
	}
	else
	{
		str+=wxT("<tr>");
	}

	str+=wxT("<td><b>");
	str+=strParamName;
	str+=wxT("</b></td>");

	str+=wxT("<td><b>");
	str+=strTxt;
	str+=wxT("</b></td>");

	str+=wxT("<td><b>");
	strStatus = st(0, bLog);
	str+=strStatus;
	str+=wxT("</b></td>");

	str+=wxT("</tr>");

	++nOrder;

	if ( bLog )
	{
		LOGENTRY entry;
		entry.strCustomEvent = _("ADSL line problem detected");
		entry.strCustomEvent+=wxT(": ");
		entry.strCustomEvent+= strParamName;
		entry.strCustomEvent+=wxT(" ");
		entry.strCustomEvent+=strStatus;

		wxGetApp().GetMainWnd()->GetLogic().AddToLog(entry, 3600);
	}

	return str;
}

//////////////////////////////////////////////////////////
//
void CADSLTab::ExecuteXML( const std::string& strXML )
{
	wxString strW = wxString::FromAscii( strXML.c_str() );
	wxGetApp().GetMainWnd()->GetLogic().SendCMDToRouter(cCmdExecuteModemXML, strW, cCmdSubCodeADSLTweak);
}

void CADSLTab::SaveExecuteXML( const std::string& strXML )
{
	wxGetApp().GetMainWnd()->GetConfig().SaveADSLXML( wxString::FromAscii(strXML.c_str()));
}

std::string CADSLTab::LoadExecuteXML()
{
	std::string str;

	wxString strXML = wxGetApp().GetMainWnd()->GetConfig().LoadADSLXML();

	str = (const char*)strXML.ToAscii();

	return str;
}

wxString CADSLTab::GetLog()
{
	wxString str, strTmp;

	if ( wxGetApp().GetMainWnd()->GetPropStorage().GetEnableADSLLog() )
	{
		if ( IsADSLBuiltIN() )
		{
			if ( !IsADSLineConnected() )
			{
				str+=_("ADSL line disconnected. ");				
			}
		}

		if ( IsADSLBuiltIN() && IsADSLineConnected() )
		{
			CMarkupSTL	doc;

			if ( doc.SetDoc( m_strXML.c_str() ) )
			{
				if ( doc.FindChildElem(ADSL_STAT_TAG) )
				{
					strTmp=AddLogLineTxt(doc, ADSL_LINE_STATUS_ATTR,_("Status"), wxT("%d"));
					if ( !strTmp.empty() )
					{
						str+=strTmp;
					}

					strTmp=AddLogLineTxt(doc, ADSL_MODE_ATTR,_("Mode"), wxT("%3.d"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}

					strTmp=AddLogLineTxt(doc, ADSL_CHANEL_ATTR,_("Type"), wxT("%3.d"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}

					/*
					strTmp=AddLogLineTxt(doc, ADSL_TRELLIS_ATTR,_("Trellis"), wxT("%3.d"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}

					strTmp=AddLogLineTxt(doc, ADSL_LINK_POWER_STATE_ATTR,_("Link Power State"), wxT("%3.d"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}*/

					strTmp=AddLogLine(doc, ADSL_DISC_COUNT_ATTR,_("Disconnect count"), wxT("%d"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}

					strTmp=AddLogLine(doc, ADSL_D_ATTN_ATTR,_("Downstream Line Attenuation"), wxT("%3.d db"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}

					strTmp=AddLogLine(doc, ADSL_U_ATTN_ATTR,_("Upstream Line Attenuation"), wxT("%3.d db"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}

					strTmp=AddLogLine(doc, ADSL_D_SNR_ATTR,_("Downstream SNR Margin"), wxT("%3.d db"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}

					strTmp=AddLogLine(doc, ADSL_U_SNR_ATTR,_("Upstream SNR Margin"), wxT("%3.d db"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}

					strTmp=AddLogLine(doc, ADSL_D_PWR_ATTR,_("Downstream Output Power"), wxT("%3.d dBm"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}

					strTmp=AddLogLine(doc, ADSL_U_PWR_ATTR,_("Upstream Output Power"), wxT("%3.d dBm"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}

					strTmp=AddLogLine(doc, ADSL_D_CONRATE_ATTR,_("Download Connection Rate"), wxT("%3.d kbs"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}

					strTmp=AddLogLine(doc, ADSL_U_CONRATE_ATTR,_("Upload Connection Rate"), wxT("%3.d kbs"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}

					/*
					strTmp=AddLogLine(doc, ADSL_D_MAXRATE_ATTR,_("Download Attainable Rate"), wxT("%3.d kbs"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}

					strTmp=AddLogLine(doc, ADSL_U_MAXRATE_ATTR,_("Upload Attainable Rate"), wxT("%3.d kbs"));
					if ( !strTmp.empty() )
					{
						if (!str.empty() ) str+=wxT(", ");
						str+=strTmp;
					}*/

					long lVal;

					for(size_t i=0;i<sizeof(errAttr)/sizeof(errAttr[0]);i++ )
					{
						lVal = atol ( doc.GetChildAttrib(errAttr[i].szTag).c_str());
						if ( lVal )
						{
							if (!str.empty() ) str+=wxT(", ");
							str+=errAttr[i].strDesc;
							str+=wxT(": ");
							str+=wxString::Format(wxT("%d"), lVal);
						}
					}

					for(size_t i=0;i<sizeof(errAttrUp)/sizeof(errAttrUp[0]);i++ )
					{
						lVal = atol ( doc.GetChildAttrib(errAttrUp[i].szTag).c_str());
						if ( lVal )
						{
							if (!str.empty() ) str+=wxT(", ");
							str+=errAttrUp[i].strDesc;
							str+=wxT(": ");
							str+=wxString::Format(wxT("%d"), lVal);
						}
					}

					for(size_t i=0;i<sizeof(errAttrDn)/sizeof(errAttrDn[0]);i++ )
					{
						lVal = atol ( doc.GetChildAttrib(errAttrDn[i].szTag).c_str());
						if ( lVal )
						{
							if ( lVal<errAttrDn[i].stLast) errAttrDn[i].stLast=0;

							if (!str.empty() ) str+=wxT(", ");
							str+=errAttrDn[i].strDesc;
							str+=wxT(": ");
							str+=wxString::Format(wxT("%d"), lVal);
						}
					}
				}
			}
		}
	}

	return str;
}

wxString CADSLTab::AddLogLineTxt(class CMarkupSTL&	doc, const char* szAttrib,
								const wxString& strParamName,const wxString& strParamMis)
{
	unsigned int nVal(0);

	std::string strVal = doc.GetChildAttrib( szAttrib );

	if ( strVal.empty() )
		return wxT("");

	return AddLogLine( wxString::FromAscii( strVal.c_str() ), strParamName);
}

wxString CADSLTab::AddLogLine(const wxString& strTxt, const wxString& strParamName)
{
	wxString str, strStatus;
	str+=strParamName;
	str+=wxT(": ");
	str+=strTxt;

	return str;
}

wxString CADSLTab::AddLogLine(class CMarkupSTL&	doc, const char* szAttrib,
								const wxString& strParamName,const wxString& strParamMis)
{
	unsigned int nVal(0);

	std::string strVal = doc.GetChildAttrib( szAttrib );

	if ( strVal.empty() )
		return wxT("");

	nVal = atol( strVal.c_str() );
	wxString strValFormatted = wxString::Format(strParamMis, nVal);

	return AddLogLine(strValFormatted, strParamName);
}
